#include "Thread.h"
#include "CurrentThread.h"

#include <semaphore.h>

std::atomic_int Thread::numCreated_(0);

Thread::Thread(ThreadFunc func, const std::string &name)
    : started_(false)
    , joined_(false)
    , tid_(0)
    , func_(std::move(func))
    , name_(name)
{
    setDefaultName();  // 调用setDefaultName为线程分配默认名称
}

// 析构函数确保如果线程已经启动但未被join，则将其设置为detach状态，防止程序结束时线程未正确清理。
Thread::~Thread()
{
    if (started_ && !joined_)
    {
        thread_->detach(); // thread类提供的设置分离线程的方法
    }
}

/**
 * 执行start()函数是主线程,而需要获取tid_的是子线程(新线程),主线程必须等待新线程获取完tid_之后才能继续执行;
 * 但是有可能tid_没有获取到,因为线程的执行是没有顺序而言的;所以需要引入信号量,主线程必须等待上面的子线程获取
 * tid_值;当新线程没有获取tid_的时候,主线程等待在信号量上(信号量初始值为0),当获取了tid_值,信号量加1(sem_post(&sem)),
 * 通知主线程可以继续执行了;
*/
void Thread::start()  // 一个Thread对象，记录的就是一个新线程的详细信息
{
    started_ = true;
    sem_t sem;
    sem_init(&sem, false, 0);

    // 开启新线程(子线程)
    thread_ = std::shared_ptr<std::thread>(new std::thread([&](){
        // 获取线程的tid值
        tid_ = CurrentThread::tid();
        sem_post(&sem);
        // 开启一个新线程，专门执行该线程函数
        func_(); // one loop per thread
    }));

    // 这里必须等待获取上面 新创建的线程 的tid值
    sem_wait(&sem);
}

void Thread::join()
{
    joined_ = true;
    thread_->join();
}

void Thread::setDefaultName()
{
    int num = ++numCreated_;
    if (name_.empty())
    {
        char buf[32] = {0};
        snprintf(buf, sizeof buf, "Thread%d", num);
        name_ = buf;
    }
}

